package com.example.demo_redis_test.dynamicproxy;

public class Test {
    /**
     * JDK动态代理实现
     * @param args
     */
    public static void main(String[] args){
        //ThreadLocal<Yaml> ThreadLocal = new ThreadLocal<Yaml>();
        //(5)打开这个开关，可以把生成的代理类保存到磁盘
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        //(6)创建目标对象（被代理对象）
        DynamicProxyInterface service = new DynamicProxyInterfaceImpl();
        //(7)创建一个InvocationHandler实例，并传递被代理对象
        MyInvocationHandler handler = new MyInvocationHandler(service);
        //(8)生成代理类
        DynamicProxyInterface proxy = (DynamicProxyInterface) handler.getProxy();
        proxy.add();
        proxy.addto();
    }
    /**
     * B+树，相比B树：（1）有更少的IO次数；（2）有更大的查询范围；（3）有稳定的查询次数
     * B+树的叶子节点保存索引的键值和指向下一层节点的指针，非叶子节点保存有索引的键值和数据
     * 三层的B+树，理论上可以A保存1亿条数据，1000*1000*100（100是叶子节点需要保存数据）
     * 多路平衡查找树
     */
    /**
     * Redis支持的数据类型
     * （1） String 保存热数据、登录的tokem值，计数器
     * （List） 微信朋友圈的时间线，消息队列
     * （Hash） 存储对象
     * (Set)   不可重复的集合   共同好友，
     * （Zset）  不可重复的排序集合（优先队列）
     */
    /**
     * RabbitMQ
     * 如何保证消息不丢失
     * （1）ack确认机制；（2）补偿机制 （3）持久化（消息持久化、队列持久化、路由器）
     *
     * 四种交换机
     * direct,精确匹配路由键
     * finout,忽略路由键，相当于订阅模式(广播)，
     * topic,模糊匹配路由键
     * header
     */

    /**
     * springmvc工作原理
     * 前端发送请求到前端控制器
     * 前端控制器调用HanderMapping，通过注解或者xml解析找到具体的处理器。返回Handler
     * 前端控制器调用HandlerAdapter(处理器适配器)，经过适配到具体的controller，处理完毕后返回modelAndView
     * 前端控制器将modelAndView发送给视图解析器，去解析，返回view
     * 前端控制器对反悔的view进行渲染
     * 返回给前端页面
     */

    /**
     * 优化sql
     *  不要用子查询，要用左右连接查询
     *  where条件中能排除最多数据的放在最下面，是从最下面开始读的
     *  可以用direct就不要用group by
     *  用单列索引
     *  索引失效的场景：（1） 不等于 （2）null (3)or (4)int或者not in (5) 模糊查询 (6)组合索引，第一个索引关键需要出现
     */
    /**
     * spring ioc和aop
     *      * ioc（控制反转）是一种编程思想，将创建对象的权限交给Spring框架来处理，
     *      * ioc容器是Spring框架管理对象的容器，
     *      * 它是通过反射机制+工厂模式实现的，在实例化一个类时，
     *      * 它通过反射调用类中set方法将事先保存在Map中的类属性注入到类中。
     *
     * aop（面向切面编程）能够将那些与业务无关的，却为业务模块所使用的逻辑（事务、权限控制、日志）封装起来，
     * 降低代码重复，降低耦合度，提高代码的扩展性和可维护性
     * aop基于动态代理实现的，有jdk动态代理和cglib动态代理，jdk动态代理是通过反射来访问被代理的类，
     * 但是被代理的类必须实现接口，核心是invocationHandler和procy类，通过invoke执行代理类中的目标方法；
     * cglib动态代理是没有实现接口的类,而是生成一个动态代理的子类来作为代理，拦截器调用intercept()方法，
     * 从而完成了由代理对象访问到目标对象的动态代理实现。
     * cglib动态代理参考地址：https://blog.csdn.net/yhl_jxy/article/details/80633194
     */
    /**
     * 码云的账号和密码：手机号+常用密码
     * git本地的账号：xxx
     *         密码：1428346747@qq.com
     */
    /**
     * redis参考地址：https://gper.club/articles/7e7e7f7ff5g5dgcd
     *
     * StringRedisTemplate和RedisTemplate
     * 区别主要在于他们使用的序列化类
     * RedisTemplate序列化成字节数组，存入Redis，非可读形式
     * Redis获取数据，默认将数据当做字节数组转化
     * 出现问题：如果redis里面存的是正常的数据的话，使用RedisTemplate读取值的话，是null
     * 解决：如果是存取的是字符串数据，用StringRedisTemplate
     *      复杂的对象类型，而取出的时候又不想做任何的数据转换，用RedisTemplate
     */
    /**
     * 抽象类和接口的区别
     * 1、抽象类里面可以用普通方法，而接口中的方法全部都是抽象的；
     * 2、在应用范围上来说，接口往往在程序设计的时候，用来定义程序模块的功能，方便各模块协同工作；
     *    抽象类是对相似类进行抽象，形成一个抽象的父类可供重用！
     */
    /**
     * 如何设计一个秒杀系统
     * 在秒杀场景中最大的问题在于容易产生大并发请求、产生超卖现象和性能问题
     * 产生大并发请求解决方案：（1）在小米手机抢购的场景一般都会有10w＋的用户同时访问一个商品页面去抢购手机，通过限流或者熔断处理、服务降级处理；
     *                     （2）大量用户涌入，造成瞬间的高流量，变成一段时间平稳的流量也是设计秒杀系统很重要的思路。
 *                              实现削峰的常用的方法有利用缓存（极大提高系统读写速度）和消息中间件（削峰，主动拉取请求消息）
     * 性能问题解决方案：每个用户都等几十秒才能知道结果，那体验必然是很糟糕的；
     * 产生超卖现象解决方案：实时库存的扣减在缓存中进行，异步扣减数据库中的库存，保证缓存中和数据库中库存的最终一致性。通过redis分布式锁或者zookeeper分布式锁
     *
     *
     * 解决方案：
     * （1） 服务单一职责：抗住高并发，微服务的概念，分布式的部署，给秒杀开个服务，我们把秒杀的代码业务逻辑放一起，建立单独的秒杀库
     * （2） URL动态化，开发的人员都不知道url是什么
     * （3） Redis集群、主从同步、读写分离，哨兵，开启持久化直接无敌高可用！
     */
    /**
     * 削峰从本质上来说就是更多地延缓用户请求，以及层层过滤用户的访问需求，遵从“最后落地到数据库的请求数要尽量少”的原则。
     * 要对流量进行削峰，最容易想到的解决方案就是用消息队列来缓冲瞬时流量，
     * 把同步的直接调用转换成异步的间接推送，中间通过一个队列在一端承接瞬时的流量洪峰，在另一端平滑地将消息推送出去。
     */

/**
 * 1、整体设计详解
 *  限流削峰：通过降低实际抵达服务器的并发量，降低服务器处理压力；
 *  性能优化：从前台到硬件，优化系统各方面性能，提高服务器处理能力。
 * 1.1 服务器层的限流削峰
 * 1.1.1 流量削峰的第一层：引入了防cc机制，限制用户每分钟的最高访问次数，超出频率的请求直接拒绝，
 *                      防止用户使用脚本等方式刷请求；通过Nginx配置秒杀页面每秒的最大访问限制
 * 1.1.2 进一步削减流量：Tomcat并发参数，在通过性能压测后发现，在并发请求超出400+后，响应速度明显变慢，
 *                      后台开始出现数据库，接口等链接超时，
 * 1.1.3 削减流量-消息队列:把同步的直接调用转换成异步的间接推送，中间通过一个队列在一端承接瞬时的流量洪峰，
 *                      在另一端平滑地将消息推送出去。
 * 1.2 应用层的限流削峰
 * 1.2.1 信号量的控制：在客户端看到的是长时间没有响应或者请求失败，然后不断重试，我们更希望在这个时候响应一些信息，
 *                  比如说直接给出提示没有中奖，通知客户端不再请求，从而提高用户体验。
 * 1.2.2 用户行为识别：实时人机识别：将非法的请求拦截掉，比如脚本，黄牛等等；
 *                  风控列表：根据还可以根据一些账号或者ip平时的购物等行为进行用户画像识别出其中的黄牛，机器账号等等，维持着一个列表，对于列表中的账号可以按风险等级进行额外的拦截。
 * 1.3 应用层的性能优化
 *          性能优化是一个庞大的话题，从代码逻辑，缓存，到数据库索引，从负载均衡到读写分离，
 *          此处，性能的瓶颈在于数据库的压力，这里就聊下我们的一些解决思路
 * 1.3.1 缓存之Reids
 *          使用Redis缓存库存数量等信息，减少对数据库的压力（不直接访问数据库），预减库存数量防止卖超
 *          使用自定义序列化器，将对象进行缓存
 *          秒杀采用Redis自带的计数器，限制一个（Phone/User）一个Session在规定时间内请求次数
 *              （如有大量相同请求均视为同一操作，或者放弃90%操作）
 *          秒杀商品可采用List队列依次存入，依次取出（取到秒杀成功[将用户存入Set类型防止重复秒杀购买]，否则秒杀失败）
 *          开始抢购与结束抢购之间的约束，因为访问需要消耗时间，延迟开始，提前结束
 *  1.3.2 RabbitMQ
 *          采用MQ（同步改为异步，增高体验性），将已抢商品生成订单，再将订单信息交给MQ，可解决削峰处理
 *          MQ消费者监听（实现高可用可开辟线程池，达到高处理），将订单信息一一入库（成功减库存，失败回滚）。
 *          抢购成功立马提升用户，商品抢购中，正常生成订单。当MQ正常入库之后用户就可查询订单进行支付了
 *          开启定时任务，定时扫描订单状态是否秒杀成功（成功正常消减库存商品，失败将商品再次加入缓存队列）
 *          当MQ正常入库，可发送成功抢购消息，给用户体验性提高。
 *
 * 1.3.3 数据库优化
 *         并发的分布式系统来说，数据的一致性是一个必须考虑的问题。
 *         乐观锁：在update时使用版本号的方式保证数据唯一性，比如在用户中奖后减少已有奖品数量
 *         唯一索引：在insert时通过唯一索引保证只插入一条数据，比如建立奖品id和用户id的唯一索引，防止insert时插入多条中奖记录。
 *  发起秒杀请求，验证码是否正确，活动是否结束，用户是否在黑名单（拦截器统计访问名单），
 *  真实库存是否足够，扣减缓存中的库存，计算秒杀价格
 *  提交订单 订单入库
 *
 *  秒杀所面临的两个挑战：
 *  高并发，基本主流电商的秒杀QPS峰值都在100万+。
 *  避免超卖，如何避免购买商品人数不超过商品数量上限
 */

    /**
     * 分布式，微服务，集群的区别
     * 分布式是将一个业务拆分成多个子业务，部署在不同的服务器上面，
     * 集群是将一个业务部署在多个服务器上面。
     * 分布式是以缩短单个任务的执行时间来提升效率的，而集群则是通过提高单位时间内执行的任务数来提升效率。
     * 好的设计应该是分布式和集群的结合，先分布式再集群，具体实现就是业务拆分成很多子业务，
     * 然后针对每个子业务进行集群部署，这样每个子业务如果出了问题，整个系统完全不会受影响。
     *
     * 微服务是一种架构风格，将一个大的系统划分为多个业务模块，业务模块分别部署到不同的机器上，各个业务模块之间通过接口进行数据交互。
     * 系统中的各个微服务可被独立部署，各个微服务之间是松耦合的，每个微服务仅关注于完成一件任务并很好地完成该任务。
     *
     * 微服务的设计是为了不因为某个模块的升级和BUG影响现有的系统业务。
     * 微服务与分布式的细微差别是，微服务的应用不一定是分散在多个服务器上，他也可以是同一个服务器。
     */

    /**
     * ThreadLocal 参考地址：https://baijiahao.baidu.com/s?id=1653790035315010634&wfr=spider&for=pc
     * ThreadLocal是解决线程安全问题一个很好的思路，它通过为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题。
     * 比synchronized 更简单，更方便，更高的并发性
     * ThreadLocal使用场景或者怎么用？
     * (1)保存线程上下文信息
     * (2)线程间数据隔离，所以无法解决共享对象的更新问题，以及避免了某些情况需要考虑线程安全必须同步带来的性能损失！！！
     * ThreadLocal被回收，但是map中的entry一直不能回收的问题
     */

    /**
     * 前后端分离技术的发展，出现了跨域问题。跨域问题的根本原因是因为浏览器受到同源策略的限制，当前域名下的只能读取同域下的属性。
     * 什么叫做同源策略？就是域名、端口、协议都要相同，任何一个不同，就会出现跨域
     * 解决方案：（1）CORS （2）web sockets （3）JSONP
     */

    /**
     * 微服务的注册中心、配置中心、网关
     * 注册中心：订单服务想要调用商品服务，可以在注册中心看一下，有哪些商品服务注册进来了，那么订单服务可以随便挑一个去访问
     * 配置中心，商品服务有10台机器在部署，这样我们可以在配置中心几种呢进行配置，这样我们可以在配置中心改掉某个商品服务
     *
     */

    /**
     * 事务分为编程式事务和声明式事务
     * 声明式事务分为两种：通过xml解析或者@Transactional注解，
     * 声明式事务：基于AOP面向切面的，它将具体业务与事务处理部分解耦，代码侵入性很低
     * @Transactional注解 作用于类：public方法都配置相同的事务属性信息
     *                    作用于方法：类配置了@Transactional，方法也配置了@Transactional，
     *                                方法的事务会覆盖类的事务配置信息
     */

    /**
     * idea 快捷键
     * （1） Ctrl+Alt+v生成该对象
     */
    /**
     * HR 认可的辞职理由
     *  寻求更大的个人成长空间
     *  生活所迫需要赚钱
     */
}

